// 用户认证事务测试
const bcrypt = require('bcrypt');

// 使用动态导入来加载TypeScript模块
async function runTests() {
  try {
    // 动态导入数据库和用户模型
    const { default: sequelize } = await import('../src/lib/database');
    const { default: User } = await import('../src/models/user');
    
    // 测试配置
    const TEST_USER = {
      username: 'testuser',
      password: 'testpassword123',
      email: 'test@example.com'
    };
    
    // 全局变量
    let transaction = null;
    
    async function setupDatabase() {
      try {
        // 测试数据库连接
        await sequelize.authenticate();
        console.log('✅ 数据库连接成功');
        
        // 自动创建表（如果不存在）
        await User.sync({ alter: true });
        console.log('✅ 用户表创建/更新成功');
        
      } catch (error) {
        console.error('❌ 数据库设置失败:', error);
        process.exit(1);
      }
    }
    
    async function runTestInTransaction(testName, testFunction) {
      try {
        console.log(`\n=== 开始测试: ${testName} ===`);
        
        // 开始事务
        transaction = await sequelize.transaction();
        
        // 执行测试函数
        await testFunction();
        
        // 回滚事务
        await transaction.rollback();
        console.log(`✅ 测试通过: ${testName}`);
        console.log('✅ 事务已回滚，数据恢复原状');
        
      } catch (error) {
        // 发生错误时也回滚事务
        if (transaction) {
          await transaction.rollback();
          console.log('✅ 事务已回滚，数据恢复原状');
        }
        console.error(`❌ 测试失败: ${testName}`, error);
        throw error;
      } finally {
        transaction = null;
      }
    }
    
    async function testUserCreationAndEncryption() {
      // 测试1: 创建用户并验证密码加密
      console.log('创建测试用户...');
      
      // 在事务中创建用户
      const user = await User.create({
        username: TEST_USER.username,
        password_hash: await bcrypt.hash(TEST_USER.password, 10),
        email: TEST_USER.email
      }, { transaction });
      
      console.log(`用户创建成功，ID: ${user.id}`);
      
      // 验证用户是否存在
      const foundUser = await User.findOne({ 
        where: { username: TEST_USER.username },
        transaction 
      });
      
      if (!foundUser) {
        throw new Error('用户创建后未找到');
      }
      
      console.log(`用户查找成功: ${foundUser.username}`);
      
      // 验证密码哈希格式
      if (!foundUser.password_hash.startsWith('$2b$') && !foundUser.password_hash.startsWith('$2a$')) {
        throw new Error('密码哈希格式不正确');
      }
      
      console.log('密码哈希格式验证通过');
      
      // 验证密码加密是否有效
      const isPasswordValid = await bcrypt.compare(TEST_USER.password, foundUser.password_hash);
      if (!isPasswordValid) {
        throw new Error('密码加密验证失败');
      }
      
      console.log('密码加密验证通过');
    }
    
    async function testUserLogin() {
      // 测试2: 用户登录验证
      console.log('准备登录测试...');
      
      // 先在事务中创建一个测试用户
      const user = await User.create({
        username: TEST_USER.username,
        password_hash: await bcrypt.hash(TEST_USER.password, 10),
        email: TEST_USER.email
      }, { transaction });
      
      console.log(`测试用户创建成功: ${user.username}`);
      
      // 模拟登录过程
      console.log('开始登录验证...');
      
      // 1. 查找用户
      const foundUser = await User.findOne({ 
        where: { username: TEST_USER.username },
        transaction 
      });
      
      if (!foundUser) {
        throw new Error('登录失败: 用户不存在');
      }
      
      // 2. 验证正确密码
      const isCorrectPassword = await bcrypt.compare(TEST_USER.password, foundUser.password_hash);
      if (!isCorrectPassword) {
        throw new Error('登录失败: 正确密码验证失败');
      }
      
      console.log('✅ 正确密码登录验证通过');
      
      // 3. 验证错误密码
      const isWrongPassword = await bcrypt.compare('wrongpassword123', foundUser.password_hash);
      if (isWrongPassword) {
        throw new Error('登录失败: 错误密码验证失败');
      }
      
      console.log('✅ 错误密码登录验证通过');
      
      // 4. 验证不存在的用户登录
      const nonExistentUser = await User.findOne({ 
        where: { username: 'nonexistentuser' },
        transaction 
      });
      
      if (nonExistentUser) {
        throw new Error('登录失败: 不存在的用户不应被找到');
      }
      
      console.log('✅ 不存在用户登录验证通过');
    }
    
    async function testCleanup() {
      // 验证事务回滚后数据是否被清除
      console.log('\n=== 验证事务回滚结果 ===');
      
      // 在事务外查询，应该找不到测试用户
      const user = await User.findOne({ where: { username: TEST_USER.username } });
      
      if (user) {
        console.error('❌ 错误: 事务回滚失败，测试用户仍然存在');
        // 手动清理
        await user.destroy();
        console.log('已手动清理测试用户');
      } else {
        console.log('✅ 事务回滚成功，测试用户已被清除');
      }
    }
    
    // 执行测试
    await setupDatabase();
    await runTestInTransaction('用户创建和密码加密', testUserCreationAndEncryption);
    await runTestInTransaction('用户登录验证', testUserLogin);
    await testCleanup();
    
    console.log('\n🎉 所有测试通过！');
    
    // 关闭数据库连接
    await sequelize.close();
    console.log('\n📌 数据库连接已关闭');
    
  } catch (error) {
    console.error('\n❌ 测试执行失败:', error);
    process.exit(1);
  }
}

// 运行测试
runTests();
